//
//  OPKWebViewController.m
//  YCOpenSDK
//
//  Created by ycgame on 2020/9/23.
//

#import "SCSWebViewController.h"
#import "SCSWebViewScriptMessageObject.h"
#import "SCSHuanXinManager.h"
#import "VipCustomerManager.h"
#import "ArgumentStore.h"
#import "UserInfo.h"
#import "InitManager.h"

// webview key path
#define SCS_KP_TITLE @"title"
#define SCS_KP_CAN_GO_BACK @"canGoBack"
#define SCS_KP_CAN_GO_FORWARD @"canGoForward"
#define SCS_KP_ESTIMATED_PROGRESS @"estimatedProgress"
#define SCS_WK_CALLBACK @"callback"
#define SCS_WMN_EXIT @"exit"
#define SCS_WMN_GET_YC_GAME_INIT_DATA @"getYcGameInitData"
#define SCS_WMN_GET_UNREAD_MESSAGE @"getUnReadMessage"
#define SCS_WMN_SEND_MESSAGE_WITH_VISITOR_INFO @"sendMessageWithVisitorInfo"
#define SCS_WMN_EVALUATE_SERVICE_MESSAGE @"evaluateServiceMessage"
#define SCS_WMN_GET_HISTORY_MESSAGE_LIST @"getHistoryMessageList"
#define SCS_WMN_MARK_ALL_MESSAGE_AS_READ @"markAllMessageAsRead"
#define SCS_WMN_RECEIVE_ACTION @"receiveAction"
#define SCS_WMN_FROM_IFRAME_MESSAGE @"fromIframeMessage"

#define SCS_WJS_RECEIVE_MESSAGE @"nativeReceiveMessage"
#define SCS_WJS_FORM_IFRAME_MESSAGE @"callbackFromIframeMessage"

@interface SCSWebViewController ()<WKUIDelegate, WKNavigationDelegate, SCSWebViewScriptMessageDelegate>
@property (nonatomic, strong)WKWebView *webView;
@property (nonatomic, strong)SCSWebViewScriptMessageObject *scriptMessageObj;
@property (nonatomic, strong)UIActivityIndicatorView * activityIndicator;
@property (nonatomic, strong)UIButton *failedBackButton;
@end

@implementation SCSWebViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];
    // Do any additional setup after loading the view from its nib.
    [self initializeComponents];
    
    [self webViewLoadUrl:_url];
    
    [self setupHuaXin];
}

- (BOOL)shouldAutorotate {
    return YES;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}

- (void)dealloc {
    [_webView.configuration.userContentController removeAllUserScripts];
    //移除观察者
    [_webView removeObserver:self forKeyPath:SCS_KP_TITLE];
    [_webView removeObserver:self forKeyPath:SCS_KP_CAN_GO_BACK];
    [_webView removeObserver:self forKeyPath:SCS_KP_CAN_GO_FORWARD];
    [_webView removeObserver:self forKeyPath:SCS_KP_ESTIMATED_PROGRESS];
    NSLog(@"web dealloc");
}

// 初始化一些控件
- (void)initializeComponents {
    
    _scriptMessageObj = [[SCSWebViewScriptMessageObject alloc] initWithDelegate:self];
    WKUserContentController *userController = [[WKUserContentController alloc] init];
    
    // 注册所有消息
    NSArray *msgNames = @[SCS_WMN_EXIT,
                          SCS_WMN_EVALUATE_SERVICE_MESSAGE,
                          SCS_WMN_SEND_MESSAGE_WITH_VISITOR_INFO,
                          SCS_WMN_GET_HISTORY_MESSAGE_LIST,
                          SCS_WMN_GET_UNREAD_MESSAGE,
                          SCS_WMN_MARK_ALL_MESSAGE_AS_READ,
                          SCS_WMN_RECEIVE_ACTION,
                          SCS_WMN_GET_YC_GAME_INIT_DATA,
                          SCS_WMN_FROM_IFRAME_MESSAGE,
    ];
    for (NSString *name in msgNames) {
        [userController addScriptMessageHandler:_scriptMessageObj name:name];
    }
    
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    config.allowsInlineMediaPlayback = NO;
    config.userContentController = userController;
    _webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
    _webView.allowsBackForwardNavigationGestures = YES;
    _webView.scrollView.showsVerticalScrollIndicator = NO;
    _webView.scrollView.showsHorizontalScrollIndicator = NO;
    if (@available(iOS 11.0, *)) {
        _webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    } else {
        // Fallback on earlier versions
    }
    _webView.UIDelegate = self;
    _webView.navigationDelegate = self;
    if (@available(iOS 11.0, *)) {
//        _webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    } else {
        // Fallback on earlier versions
    }
    
    [self.webView addObserver:self
                   forKeyPath:SCS_KP_TITLE
                      options:NSKeyValueObservingOptionNew
                      context:nil];
    [self.webView addObserver:self
                   forKeyPath:SCS_KP_CAN_GO_BACK
                      options:NSKeyValueObservingOptionNew
                      context:nil];
    [self.webView addObserver:self
                   forKeyPath:SCS_KP_CAN_GO_FORWARD
                      options:NSKeyValueObservingOptionNew
                      context:nil];
    [self.webView addObserver:self
                   forKeyPath:SCS_KP_ESTIMATED_PROGRESS
                      options:0
                      context:nil];
    [self.view addSubview:_webView];
    
    _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    [self.view addSubview:_activityIndicator];
    
    _failedBackButton = [[UIButton alloc] init];
    [_failedBackButton setTitle:@"加载失败，点击返回" forState:UIControlStateNormal];
    [_failedBackButton setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal];
    _failedBackButton.titleLabel.font = [UIFont systemFontOfSize:11];
    [_failedBackButton addTarget:self action:@selector(backAction:) forControlEvents:UIControlEventTouchUpInside];
    [_failedBackButton setHidden:YES];
    [self.view addSubview:_failedBackButton];
    
    [self makeConstraints];
}

// 添加约束
- (void)makeConstraints {
    _webView.translatesAutoresizingMaskIntoConstraints = NO;
    NSLayoutConstraint *webTopConstraint = [NSLayoutConstraint constraintWithItem:_webView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
    NSLayoutConstraint *webLeftConstraint = [NSLayoutConstraint constraintWithItem:_webView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
    NSLayoutConstraint *webRightConstraint = [NSLayoutConstraint constraintWithItem:_webView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
    NSLayoutConstraint *webBottomConstraint = [NSLayoutConstraint constraintWithItem:_webView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
    [self.view addConstraints:@[webTopConstraint, webLeftConstraint, webRightConstraint, webBottomConstraint]];
    
    _activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
    NSLayoutConstraint *indicatorCenterX = [NSLayoutConstraint constraintWithItem:_activityIndicator attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
    NSLayoutConstraint *indicatorCenterY = [NSLayoutConstraint constraintWithItem:_activityIndicator attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0];
    NSLayoutConstraint *indicatorWidth = [NSLayoutConstraint constraintWithItem:_activityIndicator attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0 constant:50];
    NSLayoutConstraint *indicatorHeight = [NSLayoutConstraint constraintWithItem:_activityIndicator attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0 constant:50];
    [self.view addConstraints:@[indicatorCenterX, indicatorCenterY, indicatorWidth, indicatorHeight]];
    
    
    _failedBackButton.translatesAutoresizingMaskIntoConstraints = NO;
    NSLayoutConstraint *backButtonCenterX = [NSLayoutConstraint constraintWithItem:_failedBackButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
    NSLayoutConstraint *backButtonCenterY = [NSLayoutConstraint constraintWithItem:_failedBackButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0];
    NSLayoutConstraint *backButtonWidth = [NSLayoutConstraint constraintWithItem:_failedBackButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0 constant:150];
    NSLayoutConstraint *backButtonHeight = [NSLayoutConstraint constraintWithItem:_failedBackButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0 constant:40];
    [self.view addConstraints:@[backButtonCenterX, backButtonCenterY, backButtonWidth, backButtonHeight]];
}

- (void)webViewLoadUrl:(NSString *)url {
    NSURL *URL = [[NSURL alloc] initWithString:url];
    if (URL == nil) { return; }
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
    NSString *customUserAgent = @"yunchanggameios";
    __weak typeof(self) weakSelf = self;
    [_webView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
        NSString *userAgent = result;
        NSString *newUserAgent;
        if (![result containsString:customUserAgent]) {
            newUserAgent = [userAgent stringByAppendingString:customUserAgent];
        }else{
            newUserAgent = result;
        }
        if (@available(iOS 9.0, *)) {
            [weakSelf.webView setCustomUserAgent:newUserAgent];
        } else {
            // Fallback on earlier versions
            [weakSelf.webView setValue:newUserAgent forKey:@"applicationNameForUserAgent"];
        }
    }];
    
    [_webView loadRequest:request];
}

- (void)backAction:(UIButton *)sender {
    [self dismiss];
}

// 环信相关
- (void)setupHuaXin {
    /// 接收到IM消息
    [SCSHuanXinManager sharedInstance].receiveMessageHandler = ^(NSDictionary * _Nonnull body) {
        [self callback:SCS_WJS_RECEIVE_MESSAGE parameters:body];
    };
}

#pragma mark - 用户事件
- (void)deleteWebCache {
    if (@available(iOS 9.0, *)) {
        //allWebsiteDataTypes清除所有缓存
        NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
        NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
        [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
        }];
    } else {
        // Fallback on earlier versions
    }
}

#pragma mark - Plugin_WebViewScriptMessageDelegate
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    // 获取初始化数据
    if ([message.name isEqual:SCS_WMN_GET_YC_GAME_INIT_DATA]) {
        NSString *jsonString = message.body;
        NSDictionary *dict = [self jsonObjWithString:jsonString];
        [self webConfig:dict];
    }
    // 发送消息
    else if ([message.name isEqual:SCS_WMN_SEND_MESSAGE_WITH_VISITOR_INFO]) {
        NSString *jsonString = message.body;
        NSDictionary *dict = [self jsonObjWithString:jsonString];
        [self sendMessage:dict];
    }
    // 发送评价消息
    else if ([message.name isEqual:SCS_WMN_EVALUATE_SERVICE_MESSAGE]) {
        NSString *jsonString = message.body;
        NSDictionary *dict = [self jsonObjWithString:jsonString];
        [self sendEvaluationMessage:dict];
    }
    // 获取未读消息数
    else if ([message.name isEqual:SCS_WMN_GET_UNREAD_MESSAGE]) {
        NSString *jsonString = message.body;
        NSDictionary *dict = [self jsonObjWithString:jsonString];
        [self getUnreadMessageCount:dict];
    }
    // 标记所有消息为已读
    else if ([message.name isEqual:SCS_WMN_MARK_ALL_MESSAGE_AS_READ]) {
        [self markAllMessageAsRead];
    }
    // 获取历史消息
    else if ([message.name isEqual:SCS_WMN_GET_HISTORY_MESSAGE_LIST]) {
        NSString *jsonString = message.body;
        NSDictionary *dict = [self jsonObjWithString:jsonString];
        [self getHistoryMessageList:dict];
    }
    // 给游戏透传消息
    else if ([message.name isEqual:SCS_WMN_RECEIVE_ACTION]) {
        VipCustomerManager *manager = [VipCustomerManager getInstance];
        if (manager.delegate != nil && [manager.delegate respondsToSelector:@selector(receiveAction:)]) {
            NSString *jsonString = message.body;
            NSDictionary *dict = [self jsonObjWithString:jsonString];
            [manager.delegate receiveAction:dict];
        }
    }
    // 消息回传
    else if ([message.name isEqual:SCS_WMN_FROM_IFRAME_MESSAGE]) {
        NSString *string = message.body?:@"";
        NSString *encodeJsonString = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSString *script = [NSString stringWithFormat:@"%@('%@')", SCS_WJS_FORM_IFRAME_MESSAGE, encodeJsonString];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.webView evaluateJavaScript:script completionHandler:^(id _Nullable r, NSError * _Nullable error) {
                if (error) {
                    NSLog(@"EvaluateJavaScript Error: %@", error.localizedDescription);
                }
            }];
        });
    }
    // 退出
    else if ([message.name isEqual:SCS_WMN_EXIT]) {
        [self dismiss];
    }
}

#pragma mark -

- (void)webConfig:(NSDictionary *)dict {
    NSString *callback = dict[SCS_WK_CALLBACK];
    ArgumentStore *store = ArgumentStore.current;
    if (store.configInit == nil || store.configInit.length == 0) {
        [[InitManager getInstance] initWithAppId:store.appId uid:store.uid roleId:store.roleId callback:^(BOOL result) {
        if (result) {
            NSDictionary *config = [self jsonObjWithString:[store configInit]];
            NSDictionary *info = [UserInfo getInfo:store];
            NSDictionary *obj = @{
                @"user": info,
                @"setting": config,
            };
            [self callback:callback parameters:obj];
        } else {
            [self dismiss];
        }
      }];
    } else {
        NSDictionary *config = [self jsonObjWithString:[store configInit]];
        NSDictionary *info = [UserInfo getInfo:store];
        NSDictionary *obj = @{
            @"user": info,
            @"setting": config,
        };
        [self callback:callback parameters:obj];
    }
}

// 发送消息
- (void)sendMessage:(NSDictionary *)dict {
    NSString *callback = dict[SCS_WK_CALLBACK];
    NSString *msgType = dict[@"msgType"];
    NSString *msg = dict[@"msg"];
    NSDictionary *visitor = dict[@"visitor"];
    [[SCSHuanXinManager sharedInstance] sendMessageWithType:msgType msg:msg visitorInfo:visitor result:^(NSDictionary * _Nonnull obj) {
        NSMutableDictionary *mutableObj = [[NSMutableDictionary alloc] initWithDictionary:obj];
        mutableObj[@"msg"] = msg ?: @"";
        mutableObj[@"msgType"] = msgType ?: @"";
        [self callback:callback parameters:mutableObj.copy];
    }];
}

// 发送评价消息
- (void)sendEvaluationMessage:(NSDictionary *)dict {
    NSString *callback = dict[SCS_WK_CALLBACK];
    [[SCSHuanXinManager sharedInstance] sendEvalMsg:dict result:^(NSDictionary * _Nonnull obj) {
        [self callback:callback parameters:obj];
    }];
}

// 拉取历史消息
- (void)getHistoryMessageList:(NSDictionary *)dict {
    NSString *callback = dict[SCS_WK_CALLBACK];
    NSString *msgId = dict[@"messageId"];
    int count = [dict[@"count"] intValue];
    [[SCSHuanXinManager sharedInstance] pullMessage:msgId count:count response:^(NSDictionary * _Nonnull obj) {
        [self callback:callback parameters:obj];
    }];
}

// 获取未读消息数
- (void)getUnreadMessageCount:(NSDictionary *)dict {
    NSString *callback = dict[SCS_WK_CALLBACK];
    NSNumber *count = [[SCSHuanXinManager sharedInstance] getUnreadMsgNum]?:@(0);
    [self callback:callback parameters:@{@"count": count, @"code": @"0"}];
}

// 标记消息为已读
- (void)markAllMessageAsRead {
    [[SCSHuanXinManager sharedInstance] markAllMsgAsRead];
}

#pragma mark -

- (void)callback:(NSString *)method parameters:(NSDictionary *)params {
    NSString *jsonString = [self jsonStringWithObject:params];
    NSString *encodeJsonString = [jsonString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSString *script = [NSString stringWithFormat:@"%@(\"%@\")", method, encodeJsonString];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.webView evaluateJavaScript:script completionHandler:^(id _Nullable r, NSError * _Nullable error) {
            if (error) {
                NSLog(@"EvaluateJavaScript Error: %@", error.localizedDescription);
            }
        }];
    });
}

- (NSDictionary *)jsonObjWithString:(NSString *)str {
    NSData *jsonData = [str dataUsingEncoding:NSUTF8StringEncoding];
    NSError *error;
    NSDictionary *data = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
    if (error) { return nil; }
    return data;
}

- (NSString *)jsonStringWithObject:(NSDictionary *)obj {
    NSError *error;
    NSData *data = [NSJSONSerialization dataWithJSONObject:obj options:0 error:&error];
    if (error) { return @""; }
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

- (void)dismiss {
    [[VipCustomerManager getInstance] close];
//    dispatch_async(dispatch_get_main_queue(), ^{
//        if (self.navigationController != nil) {
//            [self.navigationController dismissViewControllerAnimated:YES completion:nil];
//        } else {
//            [self dismissViewControllerAnimated:YES completion:nil];
//        }
//    });
}


#pragma KVO
//kvo 监听进度
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    if (object == _webView) {
        if ([keyPath isEqual:SCS_KP_TITLE]) {
            self.navigationItem.title = _webView.title;
        } else if ([keyPath isEqual:SCS_KP_CAN_GO_BACK]) {
            
        } else if ([keyPath isEqual:SCS_KP_CAN_GO_FORWARD]) {
            
        } else if ([keyPath isEqual:SCS_KP_ESTIMATED_PROGRESS]) {
        
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark - WKNavigationDelegate
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"页面开始加载...");
    [_activityIndicator startAnimating];
    [_failedBackButton setHidden:YES];
}

// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"页面加载失败");
    [_activityIndicator stopAnimating];
    [_failedBackButton setHidden:NO];
}

// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    NSLog(@"开始返回内容");
}

// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    NSLog(@"页面加载完成");
    [_activityIndicator stopAnimating];
    [_failedBackButton setHidden:YES];
}

//提交发生错误时调用
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    
}

// 接收到服务器跳转请求即服务重定向时之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"重定向");
}

// 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    decisionHandler(WKNavigationActionPolicyAllow);
}

// 根据客户端受到的服务器响应头以及response相关信息来决定是否可以跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    //允许跳转
    decisionHandler(WKNavigationResponsePolicyAllow);
}

//加载不受信任的https
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential,card);
    }
}

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    if (message == nil) { return; }
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
    [alert addAction:ok];
    [self presentViewController:alert animated:YES completion:nil];
    completionHandler();
}

//进程被终止时调用
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{
    NSLog(@"进程终止");
}

@end

